home *** CD-ROM | disk | FTP | other *** search
- /* NCRScriptManager.c */
- /*
- * NCRScriptUtilities.c
- * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
- */
- /* .___________________________________________________________________________________.
- | This file is specific to the NCR chip: it contains the scripts that the chip will |
- | execute and some utilities to patch the script labels. In a production system, |
- | the script will be pre-compiled and stores in read-only memory. Well, that's the |
- | theory: in reality, NCR 53C825 scripts will probably need to be patched when the |
- | system is initialized in order to store scratch area physical addresses. We don't |
- | do this, however. |
- .___________________________________________________________________________________.
- */
-
- #include "NCRDriverPrivate.h"
- #include <stddef.h>
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * The script is generated by macros. As shown here, it is in Macintosh Big-endian
- * order. The NCR chip reads it one longword at a time using DMA. Because the PCI bus
- * is little-endian, we must reverse bytes. This will be done the first time that
- * the driver is called. In a production driver, the script would be generated by an
- * external tool and stored in the driver in its final little-endian form.
- *
- * The script "compiler" uses the following conventions:
- * offsetXXX An offset into the per-request data area. The offset will
- * reference a Table entry for a Move or Select operation.
- * 'XXXX' A label within the script itself. This is used for jump
- * resolutions. To simplify the "compiler," these are
- * post-processed when the first time the script is executed:
- * Labels are four-byte character constants. The code that
- * resolves labels is moderately crude.
- * The macros:
- * Label(name)
- * Define a label. This actually creates a NOP script
- * operation with the label in the second longword.
- * Jump(label)
- * JumpWhenPhase(phase, label)
- * JumpIfPhase(phase, label)
- * JumpIfValue(value, label)
- * JumpIfNotCarry(label)
- * Jump (always, or if the condition is true) to the label.
- * ShiftRight(register)
- * This executes MOVE register SHR to register
- * MoveWhen(offset, count, phase)
- * MoveFromWhen(offset, phase)
- * Move data to/from the SCSI bus using the specified data
- * offset and count, or table. The ...When variant interrupts
- * if a phase mismatch occurs (this would be a serious error).
- * MoveValueToRegister(constant, register)
- * Store a constant value into a register.
- * MoveRegister(srcReg, dstReg)
- * Move values between registers. Note that one of the
- * registers must be SFBR to move between any two registers.
- * MoveRegister(foo, SFBR)
- * MoveRegister(SFBR, bar)
- * Int(value)
- * Interrupt the host processor.
- * AllowDisconnect(label)
- * Clear the "interrupt on bus free" bit:
- * Move SCNTL2 & 0x7F to SCNTL2
- * WaitDisconnect(label)
- * Wait until the bus is free
- * SelectATN(offset, label)
- * Select with ATN using the table offset; jump to the label
- * if we are selected or reselected.
- * ClearACK(label)
- * Clear ACK to accept message bytes.
- * ClearATN(label)
- * Clear the ATN line.
- */
- #define NOP 0x80000000 /* Jump never */
- #define OP_MASK (bit31 | bit30) /* Select the operator type */
- #define IO_OP (bit30)
- #define JUMP_OP (bit31)
- #define MEMORY_MOVE_OP (bit31 | bit30)
- #define OPCODE(op) ((op) & OP_MASK)
- #define IsMemoryMoveOp(op) (OPCODE(op) == MEMORY_MOVE_OP)
- #define IsLabel(op) ((op) == NOP)
-
- /*
- * A label is a no-op instruction - the label name is in the second word. If you add
- * instructions that take labels, be sure to update the kMaxLabels parameter to ensure
- * that the label resolver has enough space.
- *
- * Scripts always start with the ScriptStart instruction - this is used to identify
- * compiled scripts.
- *
- */
- #define Label(label) NOP, label
- #define ScriptStart Label(kScriptStartLabel)
-
- /*
- * All Jump instructions take a mandatory label.
- */
- #define Jump(label) 0x80880000, label
- #define JumpIfWhen(phase, mod, label) \
- (0x80800000 | ((phase) << 24) | (mod)), label
- #define ifTrue bit19
- #define ifPhase bit17
- #define ifWait bit16
- #define JumpIfPhase(phase, label) \
- JumpIfWhen(phase, ifTrue | ifPhase, label)
- #define JumpWhenPhase(phase, label) \
- JumpIfWhen(phase, ifWait | ifTrue | ifPhase, label)
- #define JumpWhenNotPhase(phase, label) \
- JumpIfWhen(phase, ifWait | ifPhase, label)
- #define JumpIfNotPhase(phase, label) \
- JumpIfWhen(phase, ifPhase, label)
- /*
- * The NCR Mask causes bits to be ignored. We use a positive mask. I.e.,
- * JumpIfMaskedEquals == (SFBR & mask) == value
- */
- #define JumpIfMaskedEquals(mask, value, label) \
- (0x808C0000 \
- | (((~mask) & 0xFF) << 8) \
- | value), label
- #define JumpIfEqual(value, label) (0x808C0000 | value), label
- #define JumpIfMaskedNotEquals(mask, value, label) \
- (0x80840000 \
- | (((~mask) & 0xFF) << 8) \
- | value), label
- #define JumpIfNotEqual(value, label) (0x80840000 | value), label
-
- #define JumpIfBitSet(value, label) (0x808C0000 | (value << 8) | value), label
- #define JumpIfBitClear(value, label) (0x80840000 | (value << 8) | value), label
- #define JumpIfNotCarry(label) 0x80A00000, label
- #define WaitDisconnect() 0x48000000, 0
- #define SelectATN(offset, label) (0x47000000 | offset), label
- #define ClearACK() (0x60000000 | bit6), 0
- #define ClearATN() (0x60000000 | bit3), 0
- #define ClearTarget() (0x60000000 | bit9), 0
- /*
- * MoveFrom copies data to/from the SCSI bus and memory. It is passed the offset
- * to a data table that has the actual physical address and byte count. This
- * could have been simpler, not that we're whining or anything, right?
- */
- #define MoveFrom(offset, phase) 0x18000000 | (phase << 24), offset
- /*
- * Move/compute data using the NCR registers. Note that the #define'd registers
- * are offset within our I/O space -- we remove this by and'ing with 0x7F
- */
- #define MoveValueToRegister(val, reg) \
- 0x78000000 | ((val)<<8) | (((reg) & 0x7F) << 16), 0
- #define OrValueToRegister(val, reg) \
- 0x7A000000 | ((val)<<8) | (((reg) & 0x7F) << 16), 0
- #define AndValueToRegister(val, reg) \
- 0x7C000000 | ((val)<<8) | (((reg) & 0x7F) << 16), 0
- /*
- * This is actually a "register | zero -> SFBR"
- */
- #define MoveToSFBR(reg) \
- 0x72000000 | (((reg) & 0x7F) << 16), 0
- /*
- * This is actually a "SFBR | zero -> register"
- */
- #define MoveFromSFBR(reg) \
- 0x6A000000 | (((reg) & 0x7F) << 16), 0
- #if 0
- /*
- * This rotates the carry into the register high bit. We do not want this to happen.
- */
- #define ShiftRight(reg) \
- 0x7D000000 | (((reg) & 0x7F) << 16), 0
- #endif
- /*
- * Interrupt the host processor.
- */
- #define Int(status) 0x98080000, status
- /*
- * Debug interrupts used to log why the script jumps to the failure script.
- */
- #if USE_LOG_LIBRARY
- #define DebugInt(status) Int(status), /* Note trailing comma */
- #else
- #define DebugInt(status) /* Nothing */
- #endif
-
- /*
- * AllowDisconnect == move SCNTL2 & 0x7F to SCNTL2 -- prevents interrupt on disconnect
- */
- #define AllowDisconnect() 0x7C027F00, 0x00000000
-
- #define offsetDeviceID offsetof(ScriptData, deviceIDTable) /* zero */
- #define offsetIDMsg offsetof(ScriptData, idMsgTable)
- #define offsetCommand offsetof(ScriptData, commandTable)
- #define offsetData offsetof(ScriptData, dataTable)
- #define offsetStatus offsetof(ScriptData, statusTable)
- #define offsetCommandComplete offsetof(ScriptData, completeTable)
- #define offsetBitBucketIn offsetof(ScriptData, bitBucketInTable)
- #define offsetBitBucketOut offsetof(ScriptData, bitBucketOutTable)
- #define offsetIgnoredMsg offsetof(ScriptData, ignoredMsgTable)
-
- /*
- * The script will be patched when it is first executed. The CTEST0 register will
- * be set to the PB.driverAction value when the script starts to inform the script
- * whether the user's request has a data phase.
- * CTEST0 Initialized to 0 (no data), 1 (data in), or 2 (data out)
- * Will be zero on exit if the data phase was executed.
- * A word or two about debugging: as I began debugging, I added a variety of strange
- * code bits, including a number of debugging interrupts to track down a problem
- * (mentioned below). Eventually, I turned on the NCR single-step interrupt and logged
- * every program counter -- this located the bug. The next day, I removed a variety
- * of hacks, replacing them with a better version of the single-step log. I have chosen
- * to leave much of the scaffolding in place to give developers insight as to where
- * one might encounter problems developing to a new, unfamiliar, standard; and how
- * at least one reasonably experienced engineer approaches the problem.
- *
- * The primary problem I encountered was the unavailability of a compiler for the
- * NCR Script "language" -- I have emulated the script by compiling instructions
- * using the somewhat limited C pre-processor, with a simple post-processing "second
- * pass" to resolve labelled statements.
- *
- * All things considered, there were few bugs -- and initial debugging took two
- * very long days. Here are the main points:
- * 1. Longword data had to be byte-swapped for the PCI little-endian environment.
- * This includes scripts and the Table address and length values.
- * 2. There were a few simple bugs in the script macros -- nothing special, but an
- * inverted true/false bit took its toll.
- * 3. Single-step recording was added when the script kept wandering through places it
- * should not have gone. The reason for this is that I was unaware that the Jump
- * instruction does not Jump unless the "true" bit is set. Apparently, the NCR
- * chip designer learned to program on a PDP-10.
- * 4. A footnote hidden at the bottom of the page noted that the shift operation
- * shifts through the carry bit, just in case you want to implement a division
- * in the script.
- * 5. Added a bunch of extraneous interrupts in order to log precisely why the
- * script decided to jump to the failure sequence. These can now be removed.
- */
- UInt32 gNCRSCSIScript[] = {
- ScriptStart, /* 0x00 Script Start (must be at start) */
- /*
- * This transfer vector must track the definitions in NCR53C825.h
- */
- Jump('BusR'), /* 0x08 kBusResetScript Start of Bus Reset Script */
- Jump('BusX'), /* 0x10 kBusResetScriptRestart Bus reset completion */
- Jump('Scsi'), /* 0x18 kSCSICommandScript Start of SCSI Command Script */
- Jump('Fail'), /* 0x20 kSCSIRundownScript Goto I/O rundown */
- Jump('Loop'), /* 0x28 kSCSIRestartScript Goto main SCSI loop */
- /*
- *** SCSI Command Script
- */
-
- /*
- * Here we go: select the device and send the Identify message if the device
- * goes to MSG_OUT phase. SCSI-I devices may not do this; we'll clear ATN just in
- * case. Then send the command if the device is in CMD phase, otherwise, fail.
- */
- Label('Scsi'),
- SelectATN(offsetDeviceID, 'ReSe'), /* Interrupt here if selection fails */
- JumpWhenNotPhase(MSGO, 'Init'),
- MoveFrom(offsetIDMsg, MSGO),
- Label('Init'),
- ClearATN(),
- /*
- * The main phase-loop -- continue executing commands until we reach Status phase.
- */
- Label('Loop'),
- JumpWhenPhase(CMD, 'CmdP'),
- JumpIfPhase(STS, 'Stat'),
- JumpIfPhase(MSGI, 'MsgI'), /* Message reject? */
- JumpIfPhase(DATI, 'Data'),
- JumpIfPhase(DATO, 'Data'),
- DebugInt(kIntFailStrangePhase)
- Jump('Fail'), /* Strange phase */
- /*
- * Data phase common entrance. If CTEST0 is zero, interrupt -- this may be a
- * partial-preparation continuance.
- */
- Label('Data'),
- MoveToSFBR(CTEST0), /* Is data prepared? */
- JumpIfEqual(kNCRDriverNoDataPhase, 'NoDa'), /* Jump if not prepared */
- Label('DaOK'), /* All prepared, so do the transfer */
- JumpIfPhase(DATI, 'DatI'), /* Good so far, jump to the proper */
- JumpIfPhase(DATO, 'DatO'), /* phase handler */
- DebugInt(kIntDataPhaseExpected)
- Jump('Fail'), /* We should be in a data phase */
- Label('NoDa'),
- Int(kIntNeedAnotherPreparation), /* Is another preparation needed? */
- MoveToSFBR(CTEST0), /* Continued, is it prepared now? */
- JumpIfNotEqual(0, 'DaOK'), /* Yes, try the transfer again */
- DebugInt(kIntPreparationFailed)
- Jump('Fail'), /* Run the bit-bucket script */
- /*
- * Command phase - send out the command,
- * TBS: Clear a bit in CTEST0 to signal that we sent out the command.
- */
- Label('CmdP'),
- MoveFrom(offsetCommand, CMD),
- Jump('Loop'),
- /*
- * Data Out phase: CTEST0 must equal kNCRDriverOutputAllowed
- */
- Label('DatO'),
- JumpIfNotEqual(kNCRDriverOutputAllowed, 'DaOF'),
- MoveValueToRegister(kNCRDriverNoDataPhase, CTEST0),
- MoveFrom(offsetData, DATO),
- Jump('Loop'), /* Data phase completion */
- Label('DaOF'),
- DebugInt(kIntDataOutNoData)
- Jump('Fail'),
- /*
- * Data In phase: CTEST0 must equal kNCRDriverInputAllowed
- */
- Label('DatI'),
- JumpIfNotEqual(kNCRDriverInputAllowed, 'DaIF'),
- MoveValueToRegister(kNCRDriverNoDataPhase, CTEST0),
- MoveFrom(offsetData, DATI),
- /*
- * We will get a phase mismatch error here (I think) if we are in a short-
- * transfer situation. In this case, the DBC should be non-zero and the fifo's
- * empty. In this case, the interrupt service routine recovers by retrieving the
- * DBC count (for the actualTransfer computation) and restarting the script.
- */
- Jump('Loop'), /* Data phase completion */
- Label('DaIF'),
- DebugInt(kIntDataInNoData)
- Jump('Fail'),
- /*
- * Normal exit through Status Phase - store the status and expect a MSG_IN to follow.
- */
- Label('Stat'),
- MoveFrom(offsetStatus, STS),
- JumpWhenPhase(MSGI, 'CoCo'),
- DebugInt(kIntNotMsgInAfterStatus)
- Jump('Fail'),
- /*
- * Messge in during normal command processing. About all we can do is look for a
- * Message reject (to the identify message) and ignore it. We should also handle
- * other "reasonable" messages.
- *
- * This needs work -- lots of work -- for a production driver. Also, a production
- * driver needs to be able to send messages (such as "abort") during normal
- * script operation.
- */
- Label('MsgI'),
- MoveFrom(offsetIgnoredMsg, MSGI),
- ClearACK(),
- Jump('Loop'),
- /*
- * Normal exit at Command Complete message.
- */
- Label('CoCo'),
- MoveFrom(offsetCommandComplete, MSGI),
- /*
- * Final (successful) exit: ACK the Command Complete Msg and wait for bus-free.
- */
- Label('Exit'),
- AllowDisconnect(),
- ClearACK(),
- WaitDisconnect(),
- Int(noErr),
- /*
- * Failures during normal processing come here. We bit-bucket the data until the
- * target reaches STATUS phase, then try to handle the STATUS and MSG_IN messages.
- *
- * This is not quite sufficient: we should check for REQ -- if it is not set,
- * we should set ATN and wait for REQ again. MSGO will then send a SCSI abort
- * byte (we could do this in the script by moving kScsiMsgAbort to the SFBR)
- * Hmm, we could probably do the entire bit bucket in the script by fiddling
- * with the SFBR register.
- */
- Label('Fail'),
- JumpIfNotPhase(MSGI, 'Foop'),
- Label('FMsI'),
- MoveFrom(offsetBitBucketIn, MSGI),
- ClearACK(),
- Label('Foop'),
- JumpWhenPhase(STS, 'FSts'),
- JumpIfPhase(DATI, 'FDaI'),
- JumpIfPhase(DATO, 'FDaO'),
- JumpIfPhase(MSGI, 'FMsI'),
- JumpIfPhase(MSGO, 'FMsO'),
- JumpIfPhase(CMD, 'FCmd'),
- Int(scsiUnableToTerminate), /* Something is seriously wrong here */
- Label('FCmd'),
- MoveFrom(offsetBitBucketOut, CMD),
- Jump('Foop'),
- Label('FDaI'),
- MoveFrom(offsetBitBucketIn, DATI),
- Jump('Foop'),
- Label('FDaO'),
- MoveFrom(offsetBitBucketOut, DATO),
- Jump('Foop'),
- Label('FMsO'),
- MoveFrom(offsetBitBucketOut, MSGO),
- Jump('Foop'),
- /*
- * Status phase after some recoverable error. Get the bytes and quit. Don't try move
- * elaborate recovery here.
- */
- Label('FSts'),
- MoveFrom(offsetStatus, STS),
- MoveFrom(offsetCommandComplete, MSGI),
- AllowDisconnect(),
- ClearACK(),
- WaitDisconnect(),
- Int(scsiSequenceFailed),
- /*
- * Jump here if this machine was selected or reselected.
- */
- Label('ReSe'),
- Int(scsiBusy), /* This is probably the wrong error */
- Jump('ReSe'),
-
- /*
- *** Bus Reset Script (This is independent of the SCSI Command script)
- */
- Label('BusR'),
- /*
- * Assert bus reset - this will interrupt the processor, but the interrupt
- * service routine notes that we asserted reset and will continue at 'BusX'
- */
- MoveValueToRegister(bit3, SCNTL1), /* This will interrupt */
- Label('NoOp'), /* This might not be needed */
- Label('BusX'), /* Bus reset completion */
- MoveValueToRegister(0, SCNTL1),
- Int(noErr),
- };
- ByteCount gNCRSCSIScriptSize = sizeof gNCRSCSIScript;
-
- #define kMaxLabels 32 /* Sizeof the label tabel */
- struct LabelTable {
- unsigned long label;
- unsigned long scriptIndex;
- };
- typedef struct LabelTable LabelTable, *LabelTablePtr;
-
- int NCRLookupSymbol(
- LabelTablePtr labelTablePtr,
- int nLabels,
- unsigned long symbolName
- );
- Boolean HasLabel(
- UInt32 opcode
- );
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Hack to patch the goto addresses in the script. This is a bit more efficient than
- * would really be necessary. It is called when the driver opens..
- */
- OSErr
- NCRPatchScript(void)
- {
- OSErr status;
- unsigned long dcmd; /* Opcode */
- unsigned long dsps; /* Second word -- has symbol */
- int scriptIndex; /* -> Script operation */
- int maxScript; /* Longwords in script */
- int labelIndex; /* -> Label in this script op */
- int offset;
- LabelTable labelTable[kMaxLabels];
- int nLabels;
- int i;
-
- Trace(NCRPatchScript);
- /*
- * First, check whether we've already patched this script. This will be
- * TRUE if we close and reopen the driver.
- */
- switch (gNCRSCSIScript[1]) {
- case kScriptStartLabel:
- /*
- * This is the first time we've seen this script: patch it and put it
- * into little-endian byte order.
- */
- status = notOpenErr;
- break;
- case 0:
- /*
- * The script has been patched.
- */
- status = noErr;
- break;
- default:
- LogHex(gNCRSCSIScript[1], "\pScript patch indicator wrong");
- status = paramErr;
- break;
- }
- if (status == notOpenErr) {
- /*
- * First call: build the label table.
- */
- nLabels = 0;
- status = noErr;
- maxScript = sizeof gNCRSCSIScript / sizeof (UInt32);
- for (scriptIndex = 0; scriptIndex < maxScript;) {
- dcmd = gNCRSCSIScript[scriptIndex++];
- dsps = gNCRSCSIScript[scriptIndex++];
- if (IsMemoryMoveOp(dcmd))
- scriptIndex++;
- if (IsLabel(dcmd)) {
- if (nLabels >= kMaxLabels)
- LogString("\pToo many labels");
- /*
- * Insertion sort (from Algorithms in C). Since there are only
- * about 20 labels, we don't need the setup time of a log(n) sort,
- * such as Shell or Heap sort.
- */
- for (i = nLabels; i >= 1 && dsps < labelTable[i - 1].label; --i)
- labelTable[i] = labelTable[i - 1];
- labelTable[i].label = dsps;
- labelTable[i].scriptIndex = scriptIndex;
- ++nLabels;
- }
- }
- /*
- * Resolve the labels.
- */
- for (scriptIndex = 0; scriptIndex < maxScript;) {
- dcmd = gNCRSCSIScript[scriptIndex++];
- labelIndex = scriptIndex;
- dsps = gNCRSCSIScript[scriptIndex++];
- if (IsMemoryMoveOp(dcmd))
- scriptIndex++;
- if (HasLabel(dcmd)) {
- offset = NCRLookupSymbol(labelTable, nLabels, dsps);
- if (offset > 0) {
- gNCRSCSIScript[labelIndex] =
- (offset - scriptIndex) * sizeof gNCRSCSIScript[0];
- }
- else {
- #if USE_LOG_LIBRARY
- WriteLogEntry(GLOBAL.logRecordPtr, 'ScrP',
- LogFormat4(kLogFormatSigned, kLogFormatAddress,
- kLogFormatAddress, kLogFormatAddress),
- labelIndex - 1,
- dcmd,
- dsps,
- "\pUndef script"
- );
- #endif
- status = paramErr;
- break;
- }
- }
- }
- if (status == noErr) {
- /*
- * Byte-reverse each script longword so that it can be accessed by the
- * NCR chip. This turns the Macintosh big-endian byte-ordering into the
- * PCI bus little-endian ordering.
- */
- for (scriptIndex = 0; scriptIndex < maxScript; scriptIndex++)
- gNCRSCSIScript[scriptIndex] = EndianSwap32Bit(gNCRSCSIScript[scriptIndex]);
- }
- }
- return (status);
- }
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Resolve a script symbol name, returning the index to the script operation. Return
- * zero if the symbol cannot be found. (No symbol can resolve to zero.) The algorithm
- * was adapted from Kernighan and Ritchie.
- */
- int
- NCRLookupSymbol(
- LabelTablePtr labelTablePtr,
- int nLabels,
- unsigned long symbolName
- )
- {
- register LabelTablePtr low;
- register LabelTablePtr high;
- register LabelTablePtr mid;
- int result;
-
- //** Trace(NCRLookupSymbol);
- low = labelTablePtr;
- high = &labelTablePtr[nLabels];
- result = 0;
- while (low < high) {
- mid = low + (high - low) / 2;
- if (symbolName < mid->label)
- high = mid;
- else if (symbolName > mid->label)
- low = mid + 1;
- else /* symbolName == mid->label */ {
- result = mid->scriptIndex;
- break;
- }
- }
- return (result);
- }
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * HasLabel
- *
- * This tests whether the Script opcode takes a label.
- */
- Boolean
- HasLabel(
- UInt32 opcode
- )
- {
- Boolean result;
-
- //** Trace(HasLabel);
- switch (opcode & (bit31 | bit30)) {
- case (0): /* 00 Block move instruction */
- result = FALSE;
- break;
- case (bit30): /* 01 I/O and read/write instructions */
- switch (opcode & (bit29 | bit28 | bit27)) {
- case 0: /* 01 000 Reselect takes a label */
- case bit28: /* 01 010 Wait Select takes a label */
- result = TRUE;
- break;
- default: /* 01 001 Wait Disconnect takes no label */
- /* 01 011 Set takes no label */
- /* 01 100 Clear takes no label */
- result = FALSE; /* 01 101..111 are read/write instructions */
- break;
- }
- break;
- case (bit31): /* 10 Transfer Control instructions */
- switch (opcode & (bit29 | bit28 | bit27)) {
- case 0: /* 10 000 Jump (0x80000000 == NOP) */
- case bit27: /* 10 001 Call */
- case bit28: /* 10 010 Return */
- result = TRUE;
- break;
- case (bit28 | bit27): /* 10 011 Interrupt */
- default: /* 10 1xx Reserved */
- result = FALSE;
- break;
- }
- break;
- case (bit31 | bit30): /* 11 Memory Move */
- result = FALSE;
- break;
- }
- return (result);
- }
-
-
-